/*
 * Lab9A.cpp
 *
 *  Created on: Apr 13, 2013
 *      Author: tony
 */

#include "HashTableEntry.h"
#include "HashTable.h"
using lab9::HashTable;

#include <iostream>
#include <cstddef>
using std::cout;
using std::endl;

#include <vector>
using std::vector;

#include <cstdlib> // for rand and RAND_MAX

void start_clock();
void stop_clock();

int main(){
	cout << "Lab 9 C - Hash Tables" << endl;

	const int NUMBER_OF_PAIRS = 1000;
	HashTable ht(NUMBER_OF_PAIRS);

	vector<int> keys;

	cout << "1. Generating data: " << NUMBER_OF_PAIRS << " pairs." << endl;

	const double HALF_RAND_MAX = RAND_MAX / 2;
	const double SCALE_FACTOR = 1e-6;

	for (int i=0; i<NUMBER_OF_PAIRS; i++) {
		int  x = rand() % 100000;
		double y = ( rand() - HALF_RAND_MAX ) * SCALE_FACTOR;
		ht.add( x, y );
		keys.push_back( x );
	}
	cout << "    ... done" << endl << endl;


	cout << "2. Check if existing keys are found" << endl;
	bool keysFound = true;
	for (int k : keys){
		double x = ht.get( k );
		if (x == HashTable::invalid_result){
			cout << "   No value found for existing key: " << k << endl;
			keysFound = false;
		}
	}
	if (keysFound)
		cout << "   All keys found.";
	cout << endl << endl;


	const int NUMBER_OF_ITERATIONS = 1000;
	cout << "3. Timing " << NUMBER_OF_ITERATIONS*NUMBER_OF_PAIRS << " key searches" << endl;
   /*
    * Start clock, search, and stop clock.
    */
    start_clock();
    for (int i=0; i<NUMBER_OF_ITERATIONS; i++)
    	for (int k : keys){
    		double x = ht.get( k );
    		if (x == HashTable::invalid_result){
    			cout << "   No value found for existing key: " << k << endl;
    			keysFound = false;
    		}
    	}
    stop_clock();
}


/*
 * Timing for Linux
 */
#include <sys/time.h>
#include <sys/resource.h>
timeval start_timevalue_user;
timeval start_timevalue_system;
void start_clock(){
	rusage  resource_usage;
	getrusage( RUSAGE_SELF, &resource_usage );
	start_timevalue_user   = resource_usage.ru_utime;
	start_timevalue_system = resource_usage.ru_stime;
}

void stop_clock(){
	rusage  resource_usage;
	getrusage( RUSAGE_SELF, &resource_usage );
	timeval end_timevalue_user   = resource_usage.ru_utime;
	timeval end_timevalue_system = resource_usage.ru_stime;

	double end_tu = end_timevalue_user  .tv_sec + end_timevalue_user  .tv_usec / 1.0e6;
	double end_ts = end_timevalue_system.tv_sec + end_timevalue_system.tv_usec / 1.0e6;

	double start_tu = start_timevalue_user  .tv_sec + start_timevalue_user  .tv_usec / 1.0e6;
	double start_ts = start_timevalue_system.tv_sec + start_timevalue_system.tv_usec / 1.0e6;

	cout << "   User time: " << (end_tu - start_tu)  << "  \tSystem time: " << (end_ts - start_ts) << " seconds" << endl;
}
